package org.yacon;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @author Evgeny Vetrov
 */
class ConsoleCommand
{
    private final Set<String> names;
    private final Method method;
    private final Set<CommandParameter> params;
    private final String description;
    private final Map<String, TypeConverter> converters;

    private ConsoleCommand(Set<String> names, Method method, Set<CommandParameter> params, String description,
                           Map<String, TypeConverter> converters)
    {
        this.names = names;
        this.method = method;
        this.params = params;
        this.description = description;
        this.converters = converters;
    }

    static class Builder
    {
        private Set<String> names;
        private Method method;
        private Set<CommandParameter> params;
        private String description;
        private Map<String, TypeConverter> converters = Collections.emptyMap();

        static Builder create(Set<String> names, Method method, Set<CommandParameter> params)
        {
            if (method == null)
                throw new NullPointerException("Method can't be null");
            if (names == null || names.isEmpty())
                throw new NullPointerException("Command names can't be null or empty");
            Builder builder = new Builder();
            builder.method = method;
            builder.names = Collections.unmodifiableSet(new HashSet<String>(names));
            if (params == null)
                builder.params = Collections.emptySet();
            else builder.params = Collections.unmodifiableSet(new HashSet<CommandParameter>(params));
            return builder;
        }

        Builder setDescription(String description)
        {
            this.description = description;
            return this;
        }

        Builder setConverters(Map<String, TypeConverter> converters)
        {
            if (converters == null)
                this.converters = Collections.emptyMap();
            else
                this.converters = Collections.unmodifiableMap(new HashMap<String, TypeConverter>(converters));
            return this;
        }

        ConsoleCommand build()
        {
            return new ConsoleCommand(names, method, params, description, converters);
        }
    }

    public Set<String> getNames()
    {
        return names;
    }

    public Method getMethod()
    {
        return method;
    }

    public Set<CommandParameter> getParams()
    {
        return params;
    }

    public String getDescription()
    {
        return description;
    }

    public Map<String, TypeConverter> getConverters()
    {
        return converters;
    }
}